(function($){
	var regexEnum = 
	{
		intege:"^-?[1-9]\\d*$",					//整数
		intege1:"^[1-9]\\d*$",					//正整数
		intege2:"^-[1-9]\\d*$",					//负整数
		num:"^([+-]?)\\d*\\.?\\d+$",			//数字
		num1:"^[1-9]\\d*|0$",					//正数（正整数 + 0）
		num2:"^-[1-9]\\d*|0$",					//负数（负整数 + 0）
		decmal:"^([+-]?)\\d*\\.\\d+$",			//浮点数
		decmal1:"^[[1-9]\\d*.\\d*]|0|[0.\\d*[1-9]\\d*]$",　　	//正浮点数
		decmal2:"^-([1-9]\\d*.\\d*|0.\\d*[1-9]\\d*)$",　 //负浮点数
		decmal3:"^-?([1-9]\\d*.\\d*|0.\\d*[1-9]\\d*|0?.0+|0)$",　 //浮点数
		decmal4:"^0{1}([.]\\d{1,2})?$|^[1-9]\\d*([.]{1}[0-9]{1,2})?$",　　 //非负浮点数（正浮点数 + 0）
		decmal5:"^(-([1-9]\\d*.\\d*|0.\\d*[1-9]\\d*))|0?.0+|0$",　　//非正浮点数（负浮点数 + 0）
		email:"^\\w+((-\\w+)|(\\.\\w+))*\\@[A-Za-z0-9]+((\\.|-)[A-Za-z0-9]+)*\\.[A-Za-z0-9]+$", //邮件
		color:"^[a-fA-F0-9]{6}$",				//颜色
		url:"^http[s]?:\\/\\/([\\w-]+\\.)+[\\w-]+([\\w-./?%&=#]*)?$",	//url
		chinese:"^[\\u4E00-\\u9FA5\\uF900-\\uFA2D]+$",					//仅中文
		ascii:"^[\\x00-\\xFF]+$",				//仅ACSII字符
		zipcode:"^\\d{6}$",						//邮编
		mobile:"^13[0-9]{9}|15[012356789][0-9]{8}|18[0256789][0-9]{8}|147[0-9]{8}$",				//手机
		ip4:"^(25[0-5]|2[0-4]\\d|[0-1]\\d{2}|[1-9]?\\d)\\.(25[0-5]|2[0-4]\\d|[0-1]\\d{2}|[1-9]?\\d)\\.(25[0-5]|2[0-4]\\d|[0-1]\\d{2}|[1-9]?\\d)\\.(25[0-5]|2[0-4]\\d|[0-1]\\d{2}|[1-9]?\\d)$",	//ip地址
		notempty:"^\\S+$",						//非空
		picture:"(.*)\\.(jpg|bmp|gif|ico|pcx|jpeg|tif|png|raw|tga)$",	//图片
		rar:"(.*)\\.(rar|zip|7zip|tgz)$",								//压缩文件
		date:"^\\d{4}(\\-|\\/|\.)\\d{1,2}\\1\\d{1,2}$",					//日期
		qq:"^[1-9]*[1-9][0-9]*$",				//QQ号码
		tel:"^(([0\\+]\\d{2,3}-)?(0\\d{2,3})-)?(\\d{7,8})(-(\\d{3,}))?$",	//电话号码的函数(包括验证国内区号,国际区号,分机号)
		username:"^\\w+$",						//用来用户注册。匹配由数字、26个英文字母或者下划线组成的字符串
		letter:"^[A-Za-z]+$",					//字母
		letter_u:"^[A-Z]+$",					//大写字母
		letter_l:"^[a-z]+$",					//小写字母
		idcard:"^[1-9]([0-9]{14}|[0-9]{17})$"	//身份证
	}
        var options = {
        	data:{},
        	url:"",
        	type:"post",
        	success:function(){},
    		add:function(k,v){
    			if(v.tipId==null){
					v.tipId = k+"Tip";
    			}
    			var that2 = this;
    			var valObj = $(that2.that).find("select[name='"+k+"'],input[type='text'][name='"+k+"'],input[type='hidden'][name='"+k+"'],textarea[name='"+k+"']");
    			if(this.data[k]==null){
    				this.data[k]=[];
    				
    				valObj.change(function(){
        				var errorObj = validatorItem(that2.that, k, that2.data);
        				if(errorObj != null){
        	    			$(that2.that).find("#"+v.tipId).html(errorObj.errorMsg);
        	    		} else {
        	    			$(that2.that).find("#"+v.tipId).html("");
        	    		}
        			});
    			}
    			this.data[k].push(v);
    			
    		},
    		clean:function(k){
    			if(this.data[k]!=null){
    				this.data[k]=[];
    			}
    		},
    		error:function(){
    			
    		},
    		that:null
        };
        var validatorData = {
        	min:null,
        	max:null,
        	tipId:null,
        	borId:null,
        	regExt:null,
        	regNum:null,
        	minValue:null,
        	maxValue:null,
        	errorMsg:null
        }
        
        var setErrorMsg = function(v, msg){
        	if(v.errorMsg == null){
        		v.errorMsg = msg;
        	}
        }
        
        var validatorItem = function(that, k, data){
        	var flag = true;
        	var errorObj = null;
        	var vs = data[k];
        	var valObj = $(that).find("input[type='text'][name='"+k+"'],input[type='hidden'][name='"+k+"'],textarea[name='"+k+"']")
			var val = valObj.val();
			$.each(vs, function(i,v){
				if(val == null){
					flag = false;
    			} else if((v.min != null && val.length<v.min) || (v.max != null && val.length>v.max)){
    				flag = false;
    				var errorMsg = '字数';
    				if(v.min != null){
    					errorMsg += "不少于"+v.min+" ";
    				}
    				if(v.max != null){
    					errorMsg += "不多于"+v.max+" ";
    				}
    				setErrorMsg(v, errorMsg);
    			} else if((v.minValue != null && (isNaN(parseFloat(val)) || parseFloat(val)<v.minValue)) || (v.maxValue != null && (isNaN(parseFloat(val)) || parseFloat(val)>v.maxValue))){
    				var errorMsg = '数值';
    				if(v.minValue != null){
    					errorMsg += "不小于"+v.minValue+" ";
    				}
    				if(v.maxValue != null){
    					errorMsg += "不大于"+v.maxValue+" ";
    				}
    				setErrorMsg(v, errorMsg);
    				flag = false;
    			} else if(v.regNum != null){
    				var errorMsg = '输入错误';
    				var regNum = regexEnum[v.regNum];
    				if(regNum != null){
    					var isValid = (new RegExp(regNum)).test(val)
    					if(!isValid){
    						setErrorMsg(v, errorMsg);
    						flag = false;
    					} 
    				}
    				
    			}
				if(!flag){
					valObj.focus();
					if(errorObj == null){
						errorObj = $.extend({}, validatorData, v||{});
        			}
				} else {
					$(that).find("#"+v.tipId).html("");
				}
			});
			return errorObj;
        }
        
        var main = function(that, opt){
        	opt.that = that;
        	$(that).submit(function(){
        		var errorObj = null;
        		$.each(opt.data, function(k, vs){
        			if(errorObj == null){
        				errorObj = validatorItem(that, k, opt.data);
        			}
        		});
        		
        		if(errorObj != null){
        			$(that).find("#"+errorObj.tipId).html(errorObj.errorMsg);
        			location.href="#"+errorObj.tipId;
        			//alert(errorObj.errorMsg);
        			opt.error(errorObj.errorMsg);
        			return false;
        		}
        		
        		//收集提交数据
        		var submitData = {};
        		$(that).find("select[name],input[type='text'][name],input[type='hidden'][name],textarea[name]").each(function(){
        			var name = $(this).attr("name");
        			var value = $(this).val();
        			if(submitData[name] == null){
        				submitData[name]=value;
        			} else {
        				submitData[name]+=","+value;
        			}
        			
        		});
        		$(that).find("input[type='radio'][name]:checked,input[type='checkbox'][name]:checked").each(function(){
        			var name = $(this).attr("name");
        			var value = $(this).val();
        			if(submitData[name] == null){
        				submitData[name]=value;
        			} else {
        				submitData[name]+=","+value;
        			}
        		});
        		var mask = $('<div style="position: fixed;left: 0px;right: 0px;top: 0px;bottom: 0px;background: #000;z-index: 999;opacity: 0.3;"></div>');
        		$("body").append(mask);
        		$.ajax({url:opt.url,type:opt.type,data:submitData,dataType:"json",cache:false,success:function(ret){
        			mask.remove();
        			if(!ret.success){
        				$.jjalert(ret.msg);
        				return;
        			}
        			opt.success(ret.data);
        			
        		}});
        		return false;
        	});
        	return opt;
        }
        
        

        $.fn.extend({
            jjformValidator:function(opt){
                var opt2 = $.extend({}, options, opt||{});
                return main(this, opt2);
            }
        });
    })(jQuery);
